﻿using Microsoft.VisualBasic;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.Threading.Tasks;
using YouTuber;

public class YoutubeUrl
{
    #region "Property"

    #region "public"

    public string url { get; set; }

    #endregion

    #region "private"
    private string title { get; set; }
    private string v { get; set; }
    private string firsturl { get; set; }
    private string expire { get; set; }
    private string ip { get; set; }
    private string sparams { get; set; }
    private string ipbits { get; set; }
    private string source { get; set; }
    private string ms { get; set; }
    private string cp { get; set; }
    private string key { get; set; }
    private string upn { get; set; }
    private string id { get; set; }
    private string itag { get; set; }
    private object sver { get; set; }
    private string mt { get; set; }
    private string ratebypass { get; set; }
    private string fexp { get; set; }
    private string mv { get; set; }
    private string signature { get; set; }
    private string gir { get; set; }
    private string factor { get; set; }
    private string lmt { get; set; }
    private string burst { get; set; }
    private string clen { get; set; }
    private string dur { get; set; }
    private string quality { get; set; }
    private string Type { get; set; }
    private string algorithm { get; set; }
    private string fallback_host { get; set; }
    private string s { get; set; }
    private string gcr { get; set; }
    private string cpn { get; set; }

    #endregion

    #endregion


    public async Task<List<YoutubeVideo>> getVideos(string url)
    {
        List<YoutubeVideo> l_v = new List<YoutubeVideo>();
        long countsize = 0;
        ulong tryAgain = 0;
        await Task.Run(() =>
                    {
                        while (!(tryAgain == 20))
                        {
                            foreach (string s in get_Final_Url(url))
                            {
                                YoutubeVideo v = new YoutubeVideo();
                                v.DownloadUrl = s;
                                v.VideoID = this.v;
                                v.VideoTitle = title;
                                v.SetAll();
                                countsize += v.VideoSize;
                                l_v.Add(v);
                            }
                            if (countsize != 0)
                            {
                                break; // TODO: might not be correct. Was : Exit Do
                            }
                            tryAgain += 1;

                        }
                    });
        if (countsize == 0)
        {
            YoutubeVideo v = new YoutubeVideo();
            v.VideoID = this.v;
            l_v.Clear();
            l_v.Add(v);
            return l_v;
        }


        return l_v;
    }

    private List<string> get_Final_Url(string Url)
    {
        if (string.IsNullOrEmpty(Url))
        {
            throw new Exception("Error");
        }
        List<string> FinalUrls = new List<string>();
        Url = Url.Replace("youtu.be/", "youtube.com/watch?v=").Replace("www.youtube.com", "youtube.com").Replace("youtube.com/watch#", "youtube.com/watch?").Replace("youtube.com/v/", "youtube.com/watch?v=");

        v = getParameterValue(Url, "v");

        //Url = "http://www.youtube.com/get_video_info?video_id=" + v



        string src = GetSource(Url);
        foreach (string urldecode in Get_Decoded_urls(src))
        {
            string FinalUrl = null;

            string urldecode1 = "&" + urldecode;

            try
            {
                firsturl = getParameter(urldecode1, "url");
            }
            catch (Exception ex)
            {
            }
            try
            {
                expire = getParameter(urldecode1, "expire");
            }
            catch (Exception ex)
            {
            }
            try
            {
                ip = getParameter(urldecode1, "ip");
            }
            catch (Exception ex)
            {
            }
            try
            {
                sparams = getParameter(urldecode1, "sparams");
            }
            catch (Exception ex)
            {
            }
            try
            {
                ipbits = getParameter(urldecode1, "ipbits");
            }
            catch (Exception ex)
            {
            }
            try
            {
                source = getParameter(urldecode1, "source");
            }
            catch (Exception ex)
            {
            }
            try
            {
                ms = getParameter(urldecode1, "ms");
            }
            catch (Exception ex)
            {
            }
            try
            {
                cp = getParameter(urldecode1, "cp");
            }
            catch (Exception ex)
            {
            }
            try
            {
                key = getParameter(urldecode1, "key");
            }
            catch (Exception ex)
            {
            }
            try
            {
                upn = getParameter(urldecode1, "upn");
            }
            catch (Exception ex)
            {
            }
            try
            {
                id = getParameter(urldecode1, "id");
            }
            catch (Exception ex)
            {
            }
            try
            {
                itag = getParameter(urldecode1, "itag");
            }
            catch (Exception ex)
            {
            }
            try
            {
                sver = getParameter(urldecode1, "sver");
            }
            catch (Exception ex)
            {
            }
            try
            {
                mt = getParameter(urldecode1, "mt");
            }
            catch (Exception ex)
            {
            }
            try
            {
                ratebypass = getParameter(urldecode1, "ratebypass");
            }
            catch (Exception ex)
            {
            }
            try
            {
                fexp = getParameter(urldecode1, "fexp");
            }
            catch (Exception ex)
            {
            }
            try
            {
                mv = getParameter(urldecode1, "mv");
            }
            catch (Exception ex)
            {
            }
            try
            {
                signature = getParameter(urldecode1, "signature");
            }
            catch (Exception ex)
            {
            }
            try
            {
                gir = getParameter(urldecode1, "gir");
            }
            catch (Exception ex)
            {
            }
            try
            {
                factor = getParameter(urldecode1, "factor");
            }
            catch (Exception ex)
            {
            }
            try
            {
                lmt = getParameter(urldecode1, "lmt");
            }
            catch (Exception ex)
            {
            }
            try
            {
                burst = getParameter(urldecode1, "burst");
            }
            catch (Exception ex)
            {
            }
            try
            {
                clen = getParameter(urldecode1, "clen");
            }
            catch (Exception ex)
            {
            }
            try
            {
                dur = getParameter(urldecode1, "dur");
            }
            catch (Exception ex)
            {
            }
            try
            {
                quality = getParameter(urldecode1, "quality");
            }
            catch (Exception ex)
            {
            }
            try
            {
                algorithm = getParameter(urldecode1, "algorithm");
            }
            catch (Exception ex)
            {
            }
            try
            {
                Type = getParameter(urldecode1, "type");
            }
            catch (Exception ex)
            {
            }
            try
            {
                fallback_host = getParameter(urldecode1, "fallback_host");
            }
            catch (Exception ex)
            {
            }
            try
            {
                s = getParameter(urldecode1, "s");
            }
            catch (Exception ex)
            {
            }
            try
            {
                gcr = getParameter(urldecode1, "gcr");
            }
            catch (Exception ex)
            {
            }
            try
            {
                cpn = getParameter(urldecode1, "cpn");
            }
            catch (Exception ex)
            {
            }


            //http://r1---sn-xupn5a5uxbt-j5pe.c.youtube.com/videoplayback?algorithm=throttle-factor&burst=40&clen=4598201&cp=U0hWSllMUV9HSkNONl9RRlVFOnZ2elVnVUhXRmZj&cpn=G38zGPnkRwhv5BYT&dur=289.483&expire=1375913420&factor=1.25&fexp=927606%2C919317%2C926513%2C909546%2C906397%2C929117%2C929121%2C929906%2C929907%2C929127%2C929129%2C929131%2C929930%2C925720%2C925722%2C925718%2C925714%2C929917%2C906945%2C929919%2C912521%2C932306%2C904830%2C919373%2C904122%2C938701%2C929609%2C911423%2C909549%2C900816%2C936301%2C912711%2C935802%2C906001&gcr=eg&gir=yes&id=9fe0f5101ef80a48&ip=41.199.36.220&ipbits=8&itag=140&keepalive=yes&key=yt1&lmt=1370380694750097&ms=au&mt=1375888002&mv=m&ratebypass=yes&signature=9E25ACE6692BE45766B1D6D77E645D4FF662AC05.F616A6F9F89E9BC1FC6D439A62FDE9E26F873C&source=youtube&sparams=algorithm%2Cburst%2Cclen%2Ccp%2Cdur%2Cfactor%2Cgcr%2Cgir%2Cid%2Cip%2Cipbits%2Citag%2Clmt%2Csource%2Cupn%2Cexpire&sver=3&upn=ZrEKZkgL9zE


            // "algorithm%2Cburst%2Cclen%2Ccp%2Cdur%2C" &
            string staticparams = null;
            //= "&asv=2&keepalive=yes&algorithm=throttle-factor&gcr=eg&gir=yes&sver=3"


            FinalUrl = firsturl.Substring(4) + "?" + expire + "&" + ip + "&" + sparams + "&" + ipbits + "&" + source + "&" + ms + "&" + cp + "&" + key + "&" + upn + "&" + id + "&" + itag + "&" + sver + "&" + mt + "&" + ratebypass + "&" + fexp + "&" + mv + "&" + signature + "&" + gir + "&" + factor + "&" + lmt + "&" + burst + "&" + clen + "&" + dur + "&" + algorithm + "&" + quality + "&" + Type + "&" + fallback_host + "&" + s + "&" + gcr + "&" + cpn + staticparams;
            while (FinalUrl.Contains("&&"))
            {
                FinalUrl = FinalUrl.Replace("&&", "&");
            }
            title = GetTitle(src);
            FinalUrls.Add(FinalUrl.Trim('&') + "&title=" + title);

        }
        return FinalUrls;
    }
    #region "helper"
    private static string GetTxtBtwn(string input, string start, string end, int startIndex, bool UseLastIndexOf)
    {
        int index1 = UseLastIndexOf ? input.LastIndexOf(start, startIndex) : input.IndexOf(start, startIndex);
        if (index1 == -1)
        {
            return "";
        }
        index1 += start.Length;
        int index2 = input.IndexOf(end, index1);
        if (index2 == -1)
        {
            return input.Substring(index1);
        }
        return input.Substring(index1, index2 - index1);
    }

    private static string GetTxtBtwn(string input, string start, string end, int startIndex)
    {
        return GetTxtBtwn(input, start, end, startIndex, false);
    }

    private static string GetTitle(string RssDoc)
    {
        string str14 = GetTxtBtwn(RssDoc, "'VIDEO_TITLE': '", "'", 0);
        if (string.IsNullOrEmpty(str14))
        {
            str14 = GetTxtBtwn(RssDoc, "\"title\" content=\"", "\"", 0);
        }
        if (string.IsNullOrEmpty(str14))
        {
            str14 = GetTxtBtwn(RssDoc, "&title=", "&", 0);
        }
        str14 = str14.Replace("\\", "").Replace("'", "&#39;").Replace("\"", "&quot;").Replace("<", "&lt;").Replace(">", "&gt;").Replace("+", " ").Replace("\\", " ").Replace("/", " ").Replace("|", " ").Replace("$", " ").Replace("?", " ").Replace("*", " ").Replace(":", " ").Replace("~", "");
        return str14;
    }


    #endregion

    private string GetSource(string Url)
    {
        string r = null;
        using (System.Net.WebClient Web = new System.Net.WebClient())
        {
            Web.UseDefaultCredentials = true;

            Web.Encoding = System.Text.Encoding.UTF8;
            try
            {
               r = Web.DownloadString(Url);
            }
            catch
            {

            }
        }
        return r;
    }

    private string getParameter(string urldecode, string Key)
    {
        return Key + "=" + getParameterValue(urldecode, Key);
    }
    private string getParameterValue(string urldecode, string Key)
    {
        string param = null;
        try
        {
            urldecode = urldecode.Replace("?", "&");
            param = Strings.Split(urldecode, "&" + Key + "=")[1];
            param = Strings.Split(param, "&")[0];
        }
        catch
        {
        }
        return param;
    }



    private List<string> Get_Decoded_urls(string source)
    {
        List<string> l = new List<string>();
        int index = 0;
        try
        {
            string r = Strings.Split(source, "\"url_encoded_fmt_stream_map\":")[1];
            r = Strings.Split(r, "\"")[1];
            r = Strings.Split(r, "\"")[0];

            foreach (string link_loopVariable in r.Split(','))
            {
                string link = link_loopVariable;
                link = link.Replace("sig", "signature");
                link = link.Replace("\\u0026", "&");
                link = link.Replace("&s=", "signature=");
                l.Add(System.Web.HttpUtility.UrlDecode(link));
            }

            //Dim r2 As String = Split(source, """adaptive_fmts"":")(1)
            //r2 = Split(r2, """")(1)
            //r2 = Split(r2, """")(0)

            //For Each link In r2.Split(",")

            //    link = link.Replace("sig", "signature")
            //    link = link.Replace("\u0026", "&")
            //    link = link.Replace("&s=", "signature=")
            //    l(index) &= link
            //    index += 1
            //Next


            return l;
        }
        catch (Exception ex)
        {
            return l;
        }

    }



    //http://r1---sn-xupn5a5uxbt-j5pe.c.youtube.com/videoplayback?algorithm=throttle-factor
    //burst=40
    //clen=15131733
    //cp=U0hWSllLV19HSkNONl9RRUFJOnZ2elVnVUdDSmZj
    //cpn=9H6XgXdVdsP990jX
    //dur=289.289
    //expire=1375909820
    //factor=1.25
    //fexp=927606%2C919317%2C926513%2C909546%2C906397%2C929117%2C929121%2C929906%2C929907%2C929127%2C929129%2C929131%2C929930%2C925720%2C925722%2C925718%2C925714%2C929917%2C906945%2C929919%2C912521%2C932306%2C904830%2C919373%2C904122%2C938701%2C929609%2C911423%2C909549%2C900816%2C936301%2C912711%2C935802%2C906001
    //gcr=eg
    //gir=yes
    //id=9fe0f5101ef80a48
    //ip=41.199.36.220
    //ipbits=8
    //itag=134
    //keepalive=yes
    //key=yt1
    //lmt=1370380715767398
    //ms=au
    //mt=1375884075
    //mv=m
    //ratebypass=yes
    //signature=6D7ECB677B8C7B8F9C7CDD75A76F7342E87E17C8.37829CF7FB54D590F978130519E3E585AC23EBED
    //source=youtube
    //sparams=algorithm%2Cburst%2Cclen%2Ccp%2Cdur%2Cfactor%2Cgcr%2Cgir%2Cid%2Cip%2Cipbits%2Citag%2Clmt%2Csource%2Cupn%2Cexpire
    //sver=3
    //upn=UDCOR90bXxA



    //http://r1---sn-xupn5a5uxbt-j5pe.c.youtube.com/videoplayback?expire=1375026743&
    //ip=217.55.26.165&
    //sparams=cp%2Cid%2Cip%2Cipbits%2Citag%2Cratebypass%2Csource%2Cupn%2Cexpire&
    //ipbits=8&
    //source=youtube&
    //ms=au&
    //cp=U0hWSlBNVF9JTUNONl9IR1hIOnZpdW13TWNPdUhi&
    //key=yt1&
    //upn=ihedTjEmyhI&
    //id=533132cf7c8d793f&
    //itag=37&
    //sver=3&
    //mt=1375004843&
    //ratebypass=yes&
    //fexp=927833%2C909546%2C906397%2C929117%2C929121%2C929906%2C929907%2C925720%2C925722%2C925718%2C925714%2C929917%2C929919%2C912521%2C904830%2C919373%2C904122%2C932216%2C908534%2C919387%2C936303%2C909549%2C900816%2C936301%2C912711%2C935000&
    //mv=m&
    //signature=68FC952BF45E53F1746305EE90BB1B37BDC4C397.0DE406C17761915139A9569C7452F5B42B2912C5&
    //gir=yes&
    //factor=1.25&
    //lmt=1371812773087504&
    //burst=40&
    //clen=2226716&
    //dur=160.600

}